#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include <time.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include "os_api.h"
#include "debug.h"
#include "dev_api.h"
#include "flash.h"


#define _STACK_SIZE	(5*1024)
static void* _task_stack = NULL;
static OSTaskRef _task_ref = NULL;

typedef struct{
	UINT8 flag[64];
    UINT32 len1;
    UINT8 buffer1[512];
    UINT32 len2;
    UINT8 buffer2[512];
    UINT32 len3;
    UINT8 buffer3[512];
    UINT32 len4;
    UINT8 buffer4[512];			
} flash_param_t;

static void _task(void *ptr)
{
	int ret;
	flash_param_t flashParam = {0};
	
	UINT32 appnvm_begin = get_appnvm_begin_address();
	UINT32 appnvm_end = get_appnvm_end_address();

	// appnvm 分区可以用于存储数据
	// 默认appnvm_size 12KB（如果需要调整大小，联系Fae）, 
	// 建议客户使用前8K，最后4K使用注意不要越界,一定注意别越界，
	UINT32 appnvm_size = get_appnvm_total_size();

	if (appnvm_begin <= FLASH_BASE_ADDRESS){
		LOG_PRINTF("appnvm partition may not exist!\n");
		return;
	}
	if (appnvm_end <= appnvm_begin){
		LOG_PRINTF("appnvm partition error!\n");
		return;
	}
	// 默认12KB
	if (appnvm_size < (12*1024)){
		LOG_PRINTF("appnvm_size may error!\n");
		return;
	}

	ret = hal_FlashRead(appnvm_begin-FLASH_BASE_ADDRESS, (unsigned int)&flashParam, sizeof(flash_param_t));
	if (ret != FLASH_NO_ERROR){
		LOG_PRINTF("hal_FlashRead error!\n");
		return;
	}
	if (memcmp(flashParam.flag, "FLASH_CONFIG_FLAG", strlen("FLASH_CONFIG_FLAG")) == 0){
		LOG_PRINTF("len1: %d\n", flashParam.len1);
		LOG_PRINTF("buffer1: %s\n", (char *)flashParam.buffer1);
		LOG_PRINTF("len2: %d\n", flashParam.len2);
		LOG_PRINTF("buffer2: %s\n", (char *)flashParam.buffer2);
		LOG_PRINTF("len3: %d\n", flashParam.len3);
		LOG_PRINTF("buffer3: %s\n", (char *)flashParam.buffer3);
		LOG_PRINTF("len4: %d\n", flashParam.len4);
		LOG_PRINTF("buffer4: %s\n", (char *)flashParam.buffer4);	
	} else {
		LOG_PRINTF("not found FLASH_CONFIG_FLAG\n");
	}

	memset(&flashParam, 0x00, sizeof(flash_param_t));

	sprintf((char *)flashParam.flag, "%s", "FLASH_CONFIG_FLAG");

	sprintf((char *)flashParam.buffer1, "%s", "1234567890");
	flashParam.len1 = strlen((char *)flashParam.buffer1);

	sprintf((char *)flashParam.buffer2, "%s", "qwertyuiop[]QWERTYUIOP{}");
	flashParam.len2 = strlen((char *)flashParam.buffer2);

	sprintf((char *)flashParam.buffer3, "%s", "asdfghjkl;'ASDFGHJKL:\"");
	flashParam.len3 = strlen((char *)flashParam.buffer3);

	sprintf((char *)flashParam.buffer4, "%s", "zxcvbnm,./ZXCVBNM<>?");
	flashParam.len4 = strlen((char *)flashParam.buffer4);		

	ret = hal_FlashErase4K(appnvm_begin-FLASH_BASE_ADDRESS, FLASH_SECTOR_4K);
	if (ret != FLASH_NO_ERROR){
		LOG_PRINTF("hal_FlashErase4K error!\n");
		return;
	}

	ret = hal_FlashWrite(appnvm_begin-FLASH_BASE_ADDRESS, (unsigned int)&flashParam, sizeof(flash_param_t));
	if (ret != FLASH_NO_ERROR){
		LOG_PRINTF("hal_FlashWrite error!\n");
		return;
	}

	OSATaskSleep(200);
	memset(&flashParam, 0x00, sizeof(flash_param_t));
	ret = hal_FlashRead(appnvm_begin-FLASH_BASE_ADDRESS, (unsigned int)&flashParam, sizeof(flash_param_t));
	if (ret != FLASH_NO_ERROR){
		LOG_PRINTF("hal_FlashRead error!\n");
		return;
	}

	LOG_PRINTF("flashParam.flag %s\n", flashParam.flag);
	if (memcmp(flashParam.flag, "FLASH_CONFIG_FLAG", strlen("FLASH_CONFIG_FLAG")) == 0){
		LOG_PRINTF("len1: %d\n", flashParam.len1);
		LOG_PRINTF("buffer1: %s\n", (char *)flashParam.buffer1);
		LOG_PRINTF("len2: %d\n", flashParam.len2);
		LOG_PRINTF("buffer2: %s\n", (char *)flashParam.buffer2);
		LOG_PRINTF("len3: %d\n", flashParam.len3);
		LOG_PRINTF("buffer3: %s\n", (char *)flashParam.buffer3);
		LOG_PRINTF("len4: %d\n", flashParam.len4);
		LOG_PRINTF("buffer4: %s\n", (char *)flashParam.buffer4);	
	} else {
		LOG_PRINTF("not found FLASH_CONFIG_FLAG\n");
	}	
}

int main(void)
{
    OSA_STATUS status;

	_task_stack = malloc(_STACK_SIZE);
	ASSERT(_task_stack != NULL);
	
    status = OSATaskCreate(&_task_ref, _task_stack, _STACK_SIZE, 100, "_task", _task, NULL);
    ASSERT(status == OS_SUCCESS);
	
	return 0;
}